////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copyright (c) 2009 - 2010 RacoonStudios
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this
/// software and associated documentation files (the "Software"), to deal in the Software
/// without restriction, including without limitation the rights to use, copy, modify, merge,
/// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
/// to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or
/// substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
/// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
/// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
/// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef dxplane_h__
#define dxplane_h__

#ifdef RE_USE_DX

#include "core/types.h"
#include "math/scalar.h"
#include "math/float4.h"

namespace Math
{
	class float4;
	class matrix;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \class	plane
	///
	/// \brief	Plane. 
	///
	/// \author	Markus
	/// \date	21.02.2010
	////////////////////////////////////////////////////////////////////////////////////////////////////
	__declspec(align(16))
	class plane
	{
	public:

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	plane()
		///
		/// \brief	Default constructor. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		////////////////////////////////////////////////////////////////////////////////////////////////////
		plane();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	plane(scalar a, scalar b, scalar c, scalar d)
		///
		/// \brief	Constructor. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	a	a. 
		/// \param	b	The. 
		/// \param	c	The. 
		/// \param	d	The. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		plane(scalar a, scalar b, scalar c, scalar d);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	plane(const float4 & p0, const float4 & p1, const float4 & p2)
		///
		/// \brief	Constructor. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	p0	The 0. 
		/// \param	p1	The first const float4 &. 
		/// \param	p2	The second const float4 &. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		plane(const float4 & p0, const float4 & p1, const float4 & p2);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	plane(const float4 & p, const float4 & n)
		///
		/// \brief	Constructor. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	p	The. 
		/// \param	n	The. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		plane(const float4 & p, const float4 & n);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	plane(XMVECTOR rhs)
		///
		/// \brief	Constructor. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	rhs	The right hand side. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		plane(XMVECTOR rhs);




		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void set(scalar a, scalar b, scalar c, scalar d)
		///
		/// \brief	Sets. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	a	The scalar to set. 
		/// \param	b	The scalar to set. 
		/// \param	c	The scalar to set. 
		/// \param	d	The scalar to set. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void set(scalar a, scalar b, scalar c, scalar d);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void setA(scalar a)
		///
		/// \brief	Sets a. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	a	a. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void setA(scalar a);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void setB(scalar b)
		///
		/// \brief	Sets a b. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	b	The. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void setB(scalar b);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void setC(scalar c)
		///
		/// \brief	Sets a c. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	c	The. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void setC(scalar c);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void setD(scalar d)
		///
		/// \brief	Sets a d. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	d	The. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void setD(scalar d);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar & getA()
		///
		/// \brief	Gets a. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	a. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar & getA();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar & getB()
		///
		/// \brief	Gets the b. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The b. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar & getB();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar & getC()
		///
		/// \brief	Gets the c. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The c. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar & getC();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar & getD()
		///
		/// \brief	Gets the d. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The d. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar & getD();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar getA() const
		///
		/// \brief	Gets a. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	a. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar getA() const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar getB() const
		///
		/// \brief	Gets the b. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The b. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar getB() const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar getC() const
		///
		/// \brief	Gets the c. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The c. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar getC() const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar getD() const
		///
		/// \brief	Gets the d. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \return	The d. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar getD() const;




		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	scalar dot(const float4 & f) const
		///
		/// \brief	Dots. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	f	The. 
		///
		/// \return	. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		scalar dot(const float4 & f) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool intersectline(const float4 & start, const float4 & end, float4 & outPoint)
		///
		/// \brief	Intersectlines. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	start				The start. 
		/// \param	end					The end. 
		/// \param [in,out]	outPoint	the out point. 
		///
		/// \return	true if it succeeds, false if it fails. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool intersectline(const float4 & start, const float4 & end, float4 & outPoint);




		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	static plane normalize(const plane & p)
		///
		/// \brief	Normalizes. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	p	The. 
		///
		/// \return	. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		static plane normalize(const plane & p);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	static plane transform(const plane & p, const matrix & m)
		///
		/// \brief	Transforms. 
		///
		/// \author	Markus
		/// \date	21.02.2010
		///
		/// \param	p	The. 
		/// \param	m	The. 
		///
		/// \return	. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		static plane transform(const plane & p, const matrix & m);

	protected:

		friend class matrix;

		XMVECTOR m_vec;

	private:

	};

}

#endif // RE_USE_DX

#endif // dxplane_h__